use crate::db_init::{friends_db, messages_db, FRIENDS_DB_PATH, MESSAGES_DB_PATH};
use base64::engine::general_purpose;
use base64::Engine;
use bincode::{deserialize, serialize};
use chat_core::message::{Message, MessageType, VideoData};
use chat_core::user::User;
use chat_core::utils;
use screenshots::Screen;
use serde_json::json;
use std::collections::HashMap;
use std::env;
use chrono::Utc;
use log::log;
use tauri::path::BaseDirectory;
use tauri::{AppHandle, Emitter, EventId, Listener, Manager};
use tokio::io;
use tokio::io::{AsyncWriteExt, WriteHalf};
use tokio::net::TcpStream;
use tokio::sync::broadcast;

#[tauri::command]
pub async fn connect(app: AppHandle) {
    let mut stream = TcpStream::connect("127.0.0.1:9999").await.unwrap();
    let (tx, _rx) = broadcast::channel(1);
    tokio::spawn(async move {
        let tx = tx.clone();
        let mut rx = tx.subscribe();
        let (mut reader, mut writer) = stream.split();
        app.listen("send-message", move |event| {
            let data = event.payload();
            let data: serde_json::Value = serde_json::from_str(data).unwrap();
            let msg: Message = Message {
                sender_account: data["sender_account"].as_str().unwrap().to_string(),
                to_account: data["to_account"].as_str().unwrap().to_string(),
                message_type: serde_json::to_string(&data["message_type"]).unwrap().as_str().trim_matches('"').into(),
                content: data["content"].to_string().into_bytes(),
            };
            let mt = msg.message_type.clone();
            let _ = tx.send(msg).unwrap();
            log::info!("client receive send-message emit event message type:{:?}", mt);
        });
        loop {
            tokio::select! {
                result = rx.recv() => {
                    match result{
                        Ok(message) => {
                            let mt = message.message_type.clone();
                            let _ = utils::send_data(&mut writer, message).await;
                            log::info!("client send  message from event rx write to server  successfully:{:?}",mt)
                        }
                        Err(err) => {
                            log::error!("write message failed: {}", err);
                        }
                    }
                }
                reesult = utils::read_message(&mut reader) => {
                    match reesult {
                        Ok(message) => {
                            log::info!("read message type: {:?} from server",&message.message_type);
                            let msg_str = serde_json::to_string(&message).unwrap();
                            match message.message_type {
                                MessageType::Video(VideoData{ref cmd,..}) => {
                                    if cmd == "video_call" {
                                        app.emit_to("mainWebviewWindow","receive-message-video-call", message.clone()).unwrap();
                                    }else{
                                        let now = Utc::now();
                                        // 将时间转换为 Unix 纪元以来的毫秒数
                                        let timestamp = now.timestamp_millis() as u128;
                                        app.emit_to("mediaWebviewWindow","receive-message-video", message.clone()).unwrap();
                                        log::info!("receive video message cmd: {} : timestamp: {}",cmd,timestamp);
                                    }
                                }
                                _ => {
                                    app.emit_to("mainWebviewWindow","receive-message", &msg_str).unwrap();
                                }
                            }
                        }
                        Err(e) => {
                            log::info!("read stream error {:?}", e);
                            writer.shutdown().await.unwrap();
                            log::info!("client shutdown writer successfully");
                            break;
                        }
                    }
                }
            }
        }
    });
    log::info!("client connect to server successfully");
}
#[tauri::command]
pub async fn add_friend(account: String, user: User) {
    log::info!("add_friend account:{},user:{:?}", account, user);
    let db = friends_db.lock().unwrap();
    match db.get(&account).unwrap() {
        Some(fs) => {
            let mut friends_list = deserialize::<Vec<User>>(&fs).unwrap();
            if !friends_list.contains(&user) {
                friends_list.push(user);
                let data = serialize(&friends_list).unwrap();
                db.insert(&account, data).unwrap();
                db.flush().unwrap();
            }
        }
        None => {
            let mut friends_list: Vec<User> = Vec::new();
            friends_list.push(user);
            db.insert(&account, serialize(&friends_list).unwrap())
                .unwrap();
            db.flush().unwrap();
        }
    }
}
// 好友列表
#[tauri::command]
pub async fn friend_list(account: String) -> Vec<User> {
    let friends_list: Vec<User> = Vec::new();
    let db = friends_db.lock().unwrap();
    match db.get(&account).unwrap() {
        Some(fs) => deserialize::<Vec<User>>(&fs).unwrap(),
        None => friends_list,
    }
}

// 本地消息列表
#[tauri::command]
pub async fn save_messages(msg: HashMap<String, Vec<Message>>) {
    let db = messages_db.lock().unwrap();
    db.clear().unwrap();
    msg.iter().for_each(|(k, v)| {
        db.insert(k, serialize(v).unwrap()).unwrap();
    });
    db.flush().unwrap();
    log::info!("save local messages data successfully");
}

// 本地消息列表
#[tauri::command]
pub async fn query_messages() -> HashMap<String, Vec<Message>> {
    let db = messages_db.lock().unwrap();
    let mut data: HashMap<String, Vec<Message>> = HashMap::new();
    db.iter().for_each(|a| match a {
        Ok((k, v)) => {
            let s = deserialize::<Vec<Message>>(&v).unwrap();
            log::info!(
                "query message key:{},value size:{:?}",
                String::from_utf8_lossy(&k),
                s.len()
            );
            data.insert(
                String::from_utf8_lossy(&k).to_string(),
                deserialize(&v).unwrap(),
            );
        }
        Err(e) => {
            log::info!("query message err {:?}", e);
        }
    });
    db.flush().unwrap();
    data
}

#[tauri::command]
pub fn screenshot(x: i32, y: i32, width: u32, height: u32) -> String {
    let screen = Screen::from_point(100, 100).unwrap();
    let image = screen
        .capture_area(
            x,
            y,
            width,
            height,
        )
        .unwrap();
    let buffer = image.buffer();
    let base64_str = general_purpose::STANDARD_NO_PAD.encode(buffer);
    base64_str
}
